package main
import "fmt"

// --- 泛型类型约束 ---
type Number interface{
	~int | ~int64 | ~float64
}
type INT int
type FLOAT float64

// --- 泛型函数：求和 ---
func Sum[T Number](nums []T) T{
	var sum T
	for _,v := range nums{
		sum += v
	}
	return sum
}

// --- 泛型函数：过滤 ---
func Filter[T any](items []T,predicate func(T) bool) []T {
	var res []T
	for _,v := range items{
		if predicate(v){
			res = append(res,v)
		}
	}
	return res
}

// --- 泛型 Stack 数据结构 ---
// type Stack[T any] struct{
// 	items []T
// }
// func (s *Stack[T]) push(val T){
// 	s.items = append(s.items,val)
// }
// func (s *Stack[T]) pop() (T,bool){
// 	if 0 == len(s.items){
// 		var zero T
// 		return zero,false
// 	}
// 	val := s.items[len(s.items) - 1]
// 	s.items = s.items[:len(s.items)-1]
// 	return val,true
// }

type Node[T any] struct{
	next *Node[T]
	val T
}
type Stack[T any] struct{
	head, tail *Node[T]
}
func (s Stack[T]) printStack(){
	for p := s.head;p != nil;p = p.next {
		fmt.Print(" ",p.val)
	}
	fmt.Println()
}
func (s *Stack[T]) push(val T){
	if s.head == nil{
		s.tail = &Node[T]{val:val}
		s.head = s.tail
	}else{
		s.tail.next = &Node[T]{val:val}
		s.tail = s.tail.next
	}
}
func (s *Stack[T]) pop() (T,bool){
	if s.head == nil {
		var zero T
		return zero,false
	}
	
	// 如果只有一个元素
	if s.head == s.tail {
		val := s.head.val
		s.head = nil
		s.tail = nil
		return val, true
	}
	
	// 找到倒数第二个节点
	current := s.head
	for current.next != s.tail {
		current = current.next
	}
	
	val := s.tail.val
	s.tail = current
	s.tail.next = nil
	return val, true
}


// --- 泛型函数：Map ---
func Map[T any,U any] (items []T,mapper func(T) U) []U {
	var res []U
	for _,v := range items{
		res = append(res,mapper(v))
	}
	return res
}

func main(){

	ints := []INT{1,2,3,4,5,6}
	floats := []FLOAT{1.0,2.0,3.0,4.0,5.0,6.0}

	fmt.Println(Sum(ints))
	fmt.Println(Sum(floats))

	odd := Filter(ints, func(i INT) bool { return i%2 != 0 })
	fmt.Println("Odd numbers:", odd)

	squares := Map(ints,func(i INT) INT { return i * i })
	fmt.Println("Squares:",squares)

	s := Stack[INT]{}
	s.push(1)
	s.push(2)
	s.push(4)
	s.push(5)
	s.push(8)

	s.printStack()

	if val,ok := s.pop();ok{
		fmt.Println("pop val:",val)
	}

	if val,ok := s.pop();ok{
		fmt.Println("pop val:",val)
	}
}